{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 記法について\n",
    "\n",
    "* Array#each : Arrayクラスのインスタンスメソッドeach\n",
    "* Thread.fork : Threadクラスのクラスメソッドfork\n",
    "* Math.#sqrt : Mathモジュールのモジュール関数sqrt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 識別子\n",
    "\n",
    "* クラス名や変数名などを構成するもの\n",
    "    * クラス、変数に付ける名前のこと\n",
    "    * 全ての文法の基盤\n",
    "* 予約語は識別子として利用できない\n",
    "    * nil, true, false, not, or, and, do, then, yield, rescure, unsure,\n",
    "    * class, module, def, undef, define?, alias, super, self, return,\n",
    "    * while, until, for, in, break, next, case, when, if, unless, else, elsif\n",
    "    * BEGIN, END, begin, end, redo, retry, \n",
    "    * `__LINE__, __FILE__, __ENCODING__`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 変数\n",
    " * rubyは変数の初期化時に変数の型を指定しない「動的型言語」"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "Fixnum\n",
      "String\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "String"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 1\n",
    "p a\n",
    "p a.class\n",
    "a = \"foo\"\n",
    "p a.class"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## ローカル変数\n",
    "\n",
    "* ローカル変数の識別子\n",
    "    * アンダースコアと英数字\n",
    "* 先頭に数字は利用できない\n",
    "    * 先頭は「英小文字」または「アンダースコア」\n",
    "* アンダースコア以外の記号は使えない\n",
    "    * ダメな例\n",
    "        * hoge-1\n",
    "        * initialized?\n",
    "        * 1_to_10\n",
    "* スコープ\n",
    "    * その代入を含むブロックまで\n",
    "    * メソッドの終わりまで\n",
    "* 初期化されていないときの参照\n",
    "    1. 代入文が実行されなかったときはnil\n",
    "    1. 代入文が無い場合は例外(NameError)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "nil\n"
     ]
    },
    {
     "ename": "NameError",
     "evalue": "undefined local variable or method `bbb' for main:Object",
     "output_type": "error",
     "traceback": [
      "\u001b[31mNameError\u001b[0m: undefined local variable or method `bbb' for main:Object",
      "\u001b[37m(pry):18:in `<main>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `load'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `<main>'\u001b[0m"
     ]
    }
   ],
   "source": [
    "### 代入分が実行されなかったときはnil\n",
    "abb =\n",
    "p abb\n",
    "\n",
    "### 代入文が無い場合は例外(NameError)\n",
    "p bbb"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### クラス定義中におけるローカル変数の参照\n",
    "\n",
    "* トップレベルで定義されたローカル変数は、クラスの内部からは参照できない\n",
    "* Rubyはクラス定義と内部のメソッドはそれぞれ独立したスコープを持つ\n",
    "    * Ruby以外では、スコープが階層構造をもつものもある\n",
    "        * クラスで定義された変数はメソッドから参照できる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "undefined local variable or method `v1' for Qux1:Class",
     "output_type": "error",
     "traceback": [
      "\u001b[31mNameError\u001b[0m: undefined local variable or method `v1' for Qux1:Class",
      "\u001b[37m(pry):14:in `<class:Qux1>'\u001b[0m",
      "\u001b[37m(pry):13:in `<main>'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:22:in `load'\u001b[0m",
      "\u001b[37m/root/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:22:in `<main>'\u001b[0m"
     ]
    }
   ],
   "source": [
    "### クラスの内部でクラスの外で定義したローカル変数は参照できない\n",
    "v1 = 1\n",
    "class Qux1\n",
    "  puts v1\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "undefined local variable or method `v1' for #<Qux2:0x007fdbaffd04e8>\n",
      "undefined local variable or method `v2' for #<Qux2:0x007fdbaffca570>\n"
     ]
    }
   ],
   "source": [
    "v1 = 1\n",
    "class Qux2\n",
    "  v2 = 2\n",
    "  def method1; v1; end\n",
    "  def method2; v2; end\n",
    "end\n",
    "\n",
    "### クラスの内部のメソッドはクラスの外で定義したローカル変数は参照できない\n",
    "begin\n",
    "  puts Qux2.new.method1\n",
    "rescue NameError => ex\n",
    "  puts ex\n",
    "end\n",
    "\n",
    "### クラスの内部のメソッドはクラスの中で定義したローカル変数は参照できない\n",
    "begin\n",
    "  puts Qux2.new.method2\n",
    "rescue NameError => ex\n",
    "  puts ex\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## インスタンス変数\n",
    "\n",
    "* 命名規則\n",
    "    * 先頭\n",
    "        * `@`\n",
    "    * 構成文字\n",
    "        * 英数字又はアンダースコア\n",
    "* スコープ\n",
    "    * そのインスタンス内\n",
    "* 初期化されていない時の参照\n",
    "    * nil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "nil\n"
     ]
    }
   ],
   "source": [
    "### インスタンス変数の初期化\n",
    "@a = 5\n",
    "p @a\n",
    "\n",
    "### 初期化されていないインスタンス変数を参照\n",
    "p @b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SyntaxError: (eval):3: `@1' is not allowed as an instance variable name\n"
     ]
    }
   ],
   "source": [
    "### @の直後に数字は設定できない(SyntaxError)\n",
    "@1 = 10\n",
    "p @1\n",
    "puts ex\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### インスタンス変数の参照"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "Quex4クラスのインスタンス変数の確認\n",
      "[:@v2]\n",
      "Quex4クラスのインスタンス変数の取得\n",
      "2\n",
      "トップレベルのインスタンス変数の確認\n",
      "[:@a, :@v1]\n"
     ]
    }
   ],
   "source": [
    "@v1 = 1\n",
    "class Qux4\n",
    "  @v2 = 2\n",
    "  def method1; @v1; end\n",
    "  def method2; @v2; end\n",
    "end\n",
    "\n",
    "puts Qux4.new.method1\n",
    "puts Qux4.new.method2\n",
    "\n",
    "puts \"Quex4クラスのインスタンス変数の確認\"\n",
    "puts Qux4.instance_variables\n",
    "\n",
    "puts \"Quex4クラスのインスタンス変数の取得\"\n",
    "puts Qux4.instance_variable_get(:@v2)\n",
    "\n",
    "puts \"トップレベルのインスタンス変数の確認\"\n",
    "puts self.instance_variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "値の設定と参照\n",
      "5\n",
      "確認\n",
      "[:@method1]\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "### アクセッサの生成を行うクラスメソッドを利用して参照\n",
    "class Qux5\n",
    "  attr_accessor :method1\n",
    "end\n",
    "\n",
    "foo1 = Qux5.new\n",
    "\n",
    "puts \"値の設定と参照\"\n",
    "foo1.method1 = 5\n",
    "puts foo1.method1\n",
    "\n",
    "puts \"確認\"\n",
    "puts foo1.instance_variables\n",
    "puts foo1.instance_variable_get(:@method1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### サブクラスからメソッド経由でインスタンス変数にアクセス"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n"
     ]
    }
   ],
   "source": [
    "class Qux6\n",
    "  attr_accessor :method1\n",
    "end\n",
    "\n",
    "class Qux6Ext < Qux6\n",
    "end\n",
    "\n",
    "qux6Ext = Qux6Ext.new\n",
    "qux6Ext.method1 = 6\n",
    "puts qux6Ext.method1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## クラス変数\n",
    "\n",
    "* 命名規則\n",
    "    * 先頭\n",
    "        * `@@`\n",
    "    * 構成文字\n",
    "        * 英数字又はアンダースコア\n",
    "* スコープ\n",
    "    * そのクラスの全インスタンス\n",
    "        * 自分自身のクラス\n",
    "        * サブクラス\n",
    "            * <font color=\"red\">サブクラスとそのスーパークラス(自分自身のクラス)で同じ値となることに注意</font>\n",
    "* 初期化されていない時の参照\n",
    "    * 例外発生(NameError)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "(pry):52: warning: class variable access from toplevel\n",
      "(pry):53: warning: class variable access from toplevel\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### クラス変数の初期化\n",
    "@@a = 5\n",
    "p @@a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "(pry):56: warning: class variable access from toplevel\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "uninitialized class variable @@b in Object\n"
     ]
    }
   ],
   "source": [
    "### 初期化されていないクラス変数を参照\n",
    "begin\n",
    "  p @@b\n",
    "rescue NameError => ex\n",
    "  puts ex\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SyntaxError: (eval):3: `@@1' is not allowed as a class variable name\n"
     ]
    }
   ],
   "source": [
    "### @@の直後に数字は設定できない\n",
    "@@1 = 10\n",
    "p @@1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### クラス変数の参照"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "元クラスのインスタンスでクラス変数の値を参照\n",
      "1\n",
      "継承先クラスのインスタンスでクラス変数の値を参照\n",
      "(レシーバを経由して参照している)\n",
      "1\n",
      "(継承先クラスのインスタンスでクラス変数の値を更新)\n",
      "元クラスのインスタンスでクラス変数の値を参照\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "class Qux7\n",
    "  @@v1 = 1\n",
    "  def method1\n",
    "    @@v1\n",
    "  end\n",
    "  def method1=(value)\n",
    "    @@v1 = value\n",
    "  end\n",
    "end\n",
    "\n",
    "class Qux7Ext < Qux7\n",
    "end\n",
    "\n",
    "qux7 = Qux7.new\n",
    "qux7Ext = Qux7Ext.new\n",
    "\n",
    "puts \"元クラスのインスタンスでクラス変数の値を参照\"\n",
    "puts qux7.method1\n",
    "\n",
    "puts \"継承先クラスのインスタンスでクラス変数の値を参照\"\n",
    "puts \"(レシーバを経由して参照している)\"\n",
    "puts qux7Ext.method1\n",
    "\n",
    "puts \"(継承先クラスのインスタンスでクラス変数の値を更新)\"\n",
    "qux7Ext.method1 = 2\n",
    "\n",
    "puts \"元クラスのインスタンスでクラス変数の値を参照\"\n",
    "puts qux7.method1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## グローバル変数\n",
    "\n",
    "* 命名規則\n",
    "    * 先頭\n",
    "        * `$`\n",
    "    * 構成文字\n",
    "        * 英数字又はアンダースコア\n",
    "* スコープ\n",
    "    * どこからでも参照可能\n",
    "* 初期化されていない時の参照\n",
    "    * nil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "nil\n"
     ]
    }
   ],
   "source": [
    "### クラス変数の初期化\n",
    "$a = 5\n",
    "p $a\n",
    "\n",
    "### 初期化されていないグローバル変数を参照\n",
    "p $b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SyntaxError: (eval):3: Can't set variable $1\n"
     ]
    }
   ],
   "source": [
    "### $の直後に数字は設定できない\n",
    "$1 = 10\n",
    "p $1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### グローバル変数の参照"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "$v1 = 1\n",
    "class Qux3\n",
    "  $v2 = 2\n",
    "  def method1; $v1; end\n",
    "  def method2; $v2; end\n",
    "  def method3; $v3 = 3; end\n",
    "end\n",
    "\n",
    "puts Qux3.new.method1\n",
    "puts Qux3.new.method2\n",
    "\n",
    "### method3を実行すると、インスタンスメソッドで定義したグローバル変数をトップレベルで参照できる\n",
    "Qux3.new.method3\n",
    "puts $v3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 定数\n",
    "\n",
    "basic_constant.ipynb に移動"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# リテラル\n",
    "\n",
    "* プログラムにそのまま記述することができる値(数値、文字列など)のこと\n",
    "    * 例\n",
    "        * 1,\n",
    "        * \"Hello\"\n",
    "        * ?あ\n",
    "            * 「?」の後にひとつ文字を入れると文字リテラル\n",
    "        * etc...\n",
    "* 変数と対になるもの\n",
    "* 文字コード以外の数値リテラルには_を含めることができる\n",
    "    * 最初と最後に_をつける事はできない\n",
    "        * 最初につけるとローカル変数と認識される\n",
    "        * 最後につけるとSyntaxError"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "あ\n",
      "undefined local variable or method `\"\\u3042\"' for main:Object\n",
      "\n",
      "0.2\n",
      "0.0012\n",
      "3+7/10i\n",
      "foobar\n"
     ]
    }
   ],
   "source": [
    "### 色々練習\n",
    "\n",
    "puts ?あ\n",
    "begin\n",
    "  puts あ\n",
    "rescue NameError => ex\n",
    "  puts ex\n",
    "end\n",
    "puts\n",
    "\n",
    "puts 0.2\n",
    "puts 1.2e-3\n",
    "\n",
    "puts 3+0.7ri\n",
    "\n",
    "#p 1_\n",
    "puts \"foo\" \"bar\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 数値リテラル\n",
    "\n",
    "* 例\n",
    "    * +12, -12, 0.1, 3.0e2(300.0), 3.0e-2(0.03)\n",
    "* 基数指示子で進数を表現できる\n",
    "    * 2進数(0b)\n",
    "    * 8進数(0o or 0)\n",
    "    * 10進数(0d)\n",
    "    * 16進数(0x)\n",
    "* アンダースコアが使える\n",
    "    * 100_000_000 = 100000000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"2進数\"\n",
      "2\n",
      "4\n",
      "\"8進数\"\n",
      "8\n",
      "8\n",
      "10\n",
      "\"10進数\"\n",
      "10\n",
      "10\n",
      "123\n",
      "\"16進数\"\n",
      "16\n",
      "9\n",
      "10\n",
      "15\n",
      "\"アンダースコア 100_000_000\"\n",
      "100000000\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "100000000"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### 2進数\n",
    "p \"2進数\"\n",
    "p 0b10\n",
    "p 0b100\n",
    "\n",
    "### 8進数\n",
    "p \"8進数\"\n",
    "p 0o10\n",
    "p 010\n",
    "p 012\n",
    "\n",
    "### 10進数\n",
    "p \"10進数\"\n",
    "p 0d10\n",
    "p 10\n",
    "p 0d123\n",
    "\n",
    "### 16進数\n",
    "p \"16進数\"\n",
    "p 0x10\n",
    "p 0x9\n",
    "p 0xA\n",
    "p 0xF\n",
    "\n",
    "### アンダースコア\n",
    "p \"アンダースコア 100_000_000\"\n",
    "p 100_000_000"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 有理数のリテラル\n",
    "\n",
    "* 例\n",
    "    * 42/10r\n",
    "    * 3.14r\n",
    "\n",
    "## 複素数のリテラル\n",
    "\n",
    "* 例\n",
    "    * 1+3i"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(21/5)\n",
      "(157/50)\n",
      "(1+3i)\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "$1+3\\imath$"
      ],
      "text/plain": [
       "(1+3i)"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### 有理数のリテラル\n",
    "p 42/10r\n",
    "p 3.14r\n",
    "\n",
    "### 複素数のリテラル\n",
    "p 1+3i"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 数値演算 (比較)\n",
    "\n",
    "* 真の場合true、偽の場合falseが返る\n",
    "* 例\n",
    "    * 1 == 1\n",
    "    * 1 != 2\n",
    "    * 1 < 2\n",
    "    * 2 >= 2\n",
    "* 以下の演算子はオーバーライドできない?\n",
    "    * !=\n",
    "    * !~\n",
    "\n",
    "# UFO演算子\n",
    "\n",
    "* 比較の結果を数値で返す\n",
    "    * 例\n",
    "        * A <=> B\n",
    "        * AがBより大きい  : 1\n",
    "        * AとBが同じ     : 0\n",
    "        * AがBより小さい  : -1\n",
    "\n",
    "# 自己代入演算子\n",
    "\n",
    "* Rubyには++, -- のようなインクリメント、デクリメント演算子は存在しない\n",
    "    * 代わりに自己代入演算子を使う\n",
    "    * 例\n",
    "        * a += 1\n",
    "        * a -= 1\n",
    "        * a *= 2\n",
    "        * a **=2\n",
    "* 最初に左のオペランドを評価する\n",
    "    * <font color=\"red\">変数に値が代入されていない場合参照でNoMethodErrorが発生する</font>\n",
    "* オーバーライドできない"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "比較演算子\n",
      "true\n",
      "false\n",
      "UFO演算子\n",
      "0\n",
      "1\n",
      "-1\n",
      "自己代入演算子\n",
      "15\n",
      "125\n",
      "undefined method `+' for nil:NilClass\n"
     ]
    }
   ],
   "source": [
    "### 比較演算子\n",
    "### 正しいとtrue、違っているとfalseが返る\n",
    "puts \"比較演算子\".force_encoding(\"utf-8\")\n",
    "p 5 == 5\n",
    "p 5 < 4\n",
    "\n",
    "### UFO演算子\n",
    "puts \"UFO演算子\".force_encoding(\"utf-8\")\n",
    "p 5 <=> 5\n",
    "p 5 <=> 4\n",
    "p 5 <=> 6\n",
    "\n",
    "### 自己代入演算子\n",
    "puts \"自己代入演算子\".force_encoding(\"utf-8\")\n",
    "a = 5\n",
    "b = 5\n",
    "p a *= 3\n",
    "p b **=3\n",
    "### cは初期化されていないのでNoMethodErro\n",
    "begin\n",
    "  c += 1\n",
    "rescue NoMethodError => ex\n",
    "  puts ex\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 継承クラスの参照"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fixnum\n",
      "Integer\n",
      "Numeric\n",
      "Object\n",
      "BasicObject\n",
      "nil\n"
     ]
    }
   ],
   "source": [
    "p 1.class # Fixnum\n",
    "p 1.class.superclass # Integer\n",
    "p 1.class.superclass.superclass # Numeric\n",
    "p 1.class.superclass.superclass.superclass # Object\n",
    "p 1.class.superclass.superclass.superclass.superclass # BasicObject\n",
    "p 1.class.superclass.superclass.superclass.superclass.superclass # nil"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 加算は実際は「+メソッド」を実行している"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p 1.+(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 再定義(オーバーライド)できない演算子\n",
    "\n",
    "* スコープ演算子\n",
    "    * ::\n",
    "* 代入演算子\n",
    "    * =\n",
    "* 条件演算子\n",
    "    * ?\n",
    "* 範囲演算子\n",
    "    * .., ...\n",
    "* 論理演算子\n",
    "    * &&\n",
    "    * and\n",
    "    * ||\n",
    "    * or\n",
    "    * not"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 論理値\n",
    "\n",
    "* true と false の2つの値が存在する\n",
    "    * TrueClass と FalseClassのインスタンス\n",
    "* falseとnil以外のオブジェクトはすべて真とみなされる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TrueClass\n",
      "FalseClass\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "FalseClass"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p true.class\n",
    "p false.class"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 論理演算子\n",
    "\n",
    "* 論理積(かつ)\n",
    "    * &&\n",
    "* 論理和(または)\n",
    "    * ||\n",
    "* 否定(でない)\n",
    "    * !"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"ok01\"\n",
      "\"ok05\"\n",
      "\"ok06\"\n",
      "\"ok07\"\n",
      "\"ok10\"\n",
      "\"ok12\"\n",
      "\"左辺で結果が確定する場合は右辺を評価しない\"\n",
      "\"ok13\"\n",
      "\"ok14\"\n",
      "nil\n",
      "false\n",
      "false\n",
      "nil\n",
      "\"論理演算子を利用した式の評価\"\n",
      "2\n",
      "nil\n",
      "nil\n",
      "false\n",
      "false\n",
      "7\n",
      "9\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "if true && true;    p \"ok01\"; end #=> \"ok01\"\n",
    "if true && false;   p \"ok02\"; end #=>\n",
    "if false && true;   p \"ok03\"; end #=>\n",
    "if false && false;  p \"ok04\"; end #=>\n",
    "\n",
    "if true || true;    p \"ok05\"; end #=> \"ok05\"\n",
    "if true || false;   p \"ok06\"; end #=> \"ok06\"\n",
    "if false || true;   p \"ok07\"; end #=> \"ok07\"\n",
    "if false || false;  p \"ok08\"; end #=>\n",
    "\n",
    "if !true;           p \"ok09\"; end #=>\n",
    "\n",
    "if true && !false;  p \"ok10\"; end #=> \"ok10\"\n",
    "\n",
    "if true && nil;     p \"ok11\"; end #=>\n",
    "\n",
    "if true && !nil;     p \"ok12\"; end #=> \"ok12\"\n",
    "\n",
    "p \"左辺で結果が確定する場合は右辺を評価しない\"\n",
    "if true || false && false;    p \"ok13\"; end #=> \"ok13\" ### 最初のtrueで確定している\n",
    "if true && true  || false;    p \"ok14\"; end #=> \"ok14\" ### 真ん中のtrueで確定している\n",
    "if true && true  && false;    p \"ok15\"; end #=>        ### 最後のfalseで確定している\n",
    "\n",
    "### 最初で確定\n",
    "p nil  && false     #=> nil\n",
    "p false && nil       #=> false\n",
    "\n",
    "### 最後で確定\n",
    "p nil || false     #=> false\n",
    "p false || nil       #=> nil\n",
    "\n",
    "p \"論理演算子を利用した式の評価\"\n",
    "p a = 1     && 2     #=> 2     ### trueが確定する右辺でその値の2が返る\n",
    "p b = nil   && 3     #=> nil   ### 左辺でnilが確定するので右辺の3は評価されない\n",
    "p c = 4     && nil   #=> nil\n",
    "p d = 5     && false #=> false\n",
    "p e = false && 6     #=> false\n",
    "\n",
    "p f = 7     || 8     #=> 7     ### 左辺でtrueが確定するのでその値の7が返る\n",
    "p g = nil   || 9     #=> 9     ### trueが確定する右辺でその値の9が返る"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 論理演算子の自己代入\n",
    "\n",
    "* 最後に評価したオペランドの値を返すことを利用した変数のデフォルト値の設定"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "4\n",
      "nil\n"
     ]
    }
   ],
   "source": [
    "#p aaa bbb           #=> NameError\n",
    "p aaa = aaa || 1    #=> 1   ### aが初期化されていないときに1を代入\n",
    "p bbb ||= 2           #=> 2   ### bが初期化されていないときに2を代入\n",
    "\n",
    "ccc = 3\n",
    "p ccc &&= 4         #=> 4   ### cが初期化(値は3)されているので4を代入\n",
    "p ddd &&= 5         #=> nil ### dが初期化されていないのでnilが入る"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 特徴的な論理演算子\n",
    "\n",
    "* 例\n",
    "  * and\n",
    "  * or\n",
    "  * not\n",
    "* &&や||や!との違い\n",
    "  * 自己代入できない\n",
    "  * 代入演算子よりも演算子の優先度が低い\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "2\n",
      "1\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "### 自己代入できない\n",
    "#p a or= 1        #=> SyntaxEror\n",
    "\n",
    "### 代入演算子よりも演算子の優先度が低い\n",
    "p a = 1 &&  2      #=> 2   ### p (1 and 2)   と同じ。論理積の結果がpに渡される\n",
    "p b = (1 and 2)    #=> 2\n",
    "p c = 1 and 2      #=> 1   ### p (1) and 2   と同じ。\n",
    "p d = 3 and nil    #=> 3   ### p (3) and nil と同じ。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 条件分岐\n",
    "\n",
    "```\n",
    "if <条件式> then\n",
    "〜\n",
    "end\n",
    "```\n",
    "<条件式>が真のとき〜の処理がされる\n",
    "\n",
    "unlessもある"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "nil\n",
      "3\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### 条件が成立したときに値を代入するという書き方ができる\n",
    "a = if true\n",
    "      1\n",
    "    end\n",
    "b = 2 if true\n",
    "cccc = 3 if false  ### 3は代入されない (代入文はあるが実行されないが、判定の結果にかかわらず変数自体は確保されている)\n",
    "p a\n",
    "p b\n",
    "p cccc ### Errorにはならずnilが出力される\n",
    "\n",
    "### elsifとelse\n",
    "a = if false then\n",
    "      1\n",
    "    elsif false\n",
    "      2\n",
    "    else\n",
    "      3\n",
    "    end\n",
    "p a   # 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 三項演算子 (条件演算子)\n",
    "\n",
    "```\n",
    "条件式 ? 式1 : 式2\n",
    "```\n",
    "条件式を評価し、成立するときは式1、しない場合は式2を評価して返す"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = true ? 1 : 2\n",
    "b = false ? 1 : 2\n",
    "p a\n",
    "p b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 擬似変数\n",
    "\n",
    "* 記述しても新たに値は生成されず、唯一のインスタンスが参照される\n",
    "    * true\n",
    "        * TrueClassのインスタンス\n",
    "    * false\n",
    "        * FalseClassのインスタンス\n",
    "    * nil\n",
    "        * NilClassのインスタンス\n",
    "            * 何もない事を表現する\n",
    "            * 他のプログラミング言語ではnullに相当\n",
    "            * インスタンス変数の初期値に利用\n",
    "    * self\n",
    "        * 現在のオブジェクト\n",
    "        \n",
    "    * `__FILE__`\n",
    "        * 現在実行しているプログラムのファイル名\n",
    "    * `__LINE__`\n",
    "        * 現在実行しているプログラムの行番号    \n",
    "    * `__ENCODING__`\n",
    "        * 現在のソースファイルのスクリプトエンコーディング"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(pry)\n",
      "\n",
      "215\n",
      "\n",
      "UTF-8\n"
     ]
    }
   ],
   "source": [
    "puts __FILE__\n",
    "puts\n",
    "\n",
    "puts __LINE__\n",
    "puts\n",
    "\n",
    "puts __ENCODING__"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 文字のリテラル\n",
    "\n",
    "* 「R」を表すString\n",
    "     * ?R\n",
    "* Ctrl+vを表すString\n",
    "    * ?\\C-v"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"R\"\n",
      "\"\\u0016\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"\\u0016\""
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p ?R\n",
    "p ?\\C-v"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 文字列\n",
    "\n",
    "* リテラル書式のバリエーションが豊富 (基本的な書式、ヒアドキュメント、パーセント記法)\n",
    "\n",
    "## 基本的な書式\n",
    "\n",
    "* ダブルクオート「\"」\n",
    "    * 式展開できる\n",
    "* シングルクオート「'」\n",
    "    * 式展開できない"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"ダブルクオート\"\n",
      "String\n",
      "\"xxyy\"\n",
      "\"xxyyzz\"\n",
      "\"シングルクオート\"\n",
      "\"xxyy\"\n",
      "\"\\#{e}zz\"\n",
      "\"文字列から数値に変換\"\n",
      "123\n",
      "456\n",
      "0\n",
      "1\n",
      "1.23\n",
      "4.56\n",
      "4.5\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "4.5"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p \"ダブルクオート\"\n",
    "a = \"xx\"\n",
    "p a.class     #=> String\n",
    "b = \"xx\" \"yy\"\n",
    "p b           #=> \"xxyy\"\n",
    "p \"#{b}zz\"    #=> \"xxyyzz\"   ### b.to_s のようにto_sメソッドが呼び出されている\n",
    "\n",
    "p \"シングルクオート\"\n",
    "e = 'xx' 'yy'\n",
    "p e           #=> \"xxyy\"\n",
    "p '#{e}zz'    #=> \"\\#{e}zz\"\n",
    "\n",
    "p \"文字列から数値に変換\"\n",
    "p \"123\".to_i\n",
    "p \"456hoge789\".to_i  #=> 456   ### hogeの前までが変換対象\n",
    "p \"hoge\".to_i        #=> 0     ### 無効の場合は0が返る\n",
    "p \"1.23\".to_i        #=> 1     ### ピリオドの前までが変換対象\n",
    "p \"1.23\".to_f        #=> 1.23\n",
    "p \"4.56.789\".to_f    #=> 4.56  ### 2番目のピリオドの前までが返還対象\n",
    "p \"4.5hoge6\".to_f    #=> 4.5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## バックスラッシュ記法\n",
    "\n",
    "\n",
    "|記入|意味|\n",
    "|---|---|\n",
    "|\\x|xそのもの|\n",
    "|\\n|改行|\n",
    "|\\s|空白|\n",
    "|\\b|バックスペース|\n",
    "|\\t|タブ|\n",
    "|\\v|垂直タブ|\n",
    "|\\r|キャリッジリターン|\n",
    "|\\a|ベル|\n",
    "|\\e|エスケープ|\n",
    "|\\nnn|8進数表記(nは0-7)|\n",
    "|\\xnn|16進数表記 (nは0-9,a-f)|\n",
    "|\\cx または \\C-x|コントロール文字 (xはASCII文字)|\n",
    "|\\M-x|メタx|\n",
    "|\\M-\\C-x|メタコントロールx|\n",
    "|\\unnnn|ユニコード文字(nは0-9,a-f,A-F)|\n",
    "|\\u{nnnn}|ユニコード文字列 スペースかタブ区切りで複数指定可能|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"A\"\n",
      "\"A\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"A\""
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### \"A\"の8進数表記と16進数表記。表示したい文字コードの数値を指定する\n",
    "p \"\\101\"\n",
    "p \"\\x41\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"A\"\n",
      "A\n",
      "A"
     ]
    }
   ],
   "source": [
    "### p,puts,printの違い\n",
    "p \"\\101\"          #=> \"A\" 引数ごとに改行、inspectメソッド、そのまま出力\n",
    "puts \"\\101\"       #=> A　改行しない、to_sメソッド、適用した結果を出力\n",
    "print \"\\101\"     #=> A　引数ごとに改行、to_sメソッド、適用した結果を出力"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## ヒアドキュメント\n",
    "\n",
    "* 基本\n",
    "    * 「<<」に続けて文字列の終端を表す任意の識別子を指定\n",
    "* 変数に代入\n",
    "* 階層が深い場合\n",
    "    * 通常終端を表す識別子の前にスペースなどの文字を記述してはいけない\n",
    "    * これを回避するには識別子の頭に「-」をつける\n",
    "* 内部の文字列をインデントさせても先頭の空白部分を無視\n",
    "    * 「~」をつける\n",
    "    * Ruby2.3以降利用可能\n",
    "* 式展開\n",
    "    * デフォルト、または「\"」で囲むと式展開できる\n",
    "    * 「'」で囲むとそのまま出力される\n",
    "* メソッドの引数として渡す、直接呼び出す"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "基本\n",
      "\"hoge\\n\"\n",
      "\n",
      "変数に代入\n",
      "\"var\\n\"\n",
      "\n",
      "識別子の頭に「-」をつけてスペースを入れられるようにする\n",
      "\"   fuga\\n     hoge\\n\"\n",
      "\n",
      "識別子の頭に「~」をつけてスペースを入れられるが実際は先頭の空白を無くす(Ruby2.3以降)\n",
      "\"fuga\\n  hoge\\n\"\n",
      "\n",
      "変数展開\n",
      "\"var\\n\"\n",
      "\"var\\n\"\n",
      "\n",
      "変数展開されない\n",
      "\"\\#{a}\\n\"\n",
      "\n",
      "メソッドの引数として渡す\n",
      "JAVA\n",
      "PHP\n",
      "Ruby\n",
      "\n",
      "直接メソッドを呼び出す\n",
      "ABC\n",
      "\n"
     ]
    }
   ],
   "source": [
    "puts \"基本\"\n",
    "p <<EOS   #=> \"hoge\\n\"\n",
    "hoge\n",
    "EOS\n",
    "puts\n",
    "\n",
    "puts \"変数に代入\"\n",
    "foo = <<EOS\n",
    "var\n",
    "EOS\n",
    "p foo    #=> \"var\\n\"\n",
    "puts\n",
    "\n",
    "puts \"識別子の頭に「-」をつけてスペースを入れられるようにする\"\n",
    "p <<-EOS   #=> \"fuga\\n\"\n",
    "   fuga\n",
    "     hoge\n",
    "  EOS\n",
    "puts\n",
    "\n",
    "puts \"識別子の頭に「~」をつけてスペースを入れられるが実際は先頭の空白を無くす(Ruby2.3以降)\"\n",
    "p <<~EOS   #=> \"fuga\\n\"\n",
    "   fuga\n",
    "     hoge\n",
    "EOS\n",
    "puts\n",
    "\n",
    "puts \"変数展開\"\n",
    "a = \"var\"\n",
    "p <<EOS    #=> \"var\\n\"\n",
    "#{a}\n",
    "EOS\n",
    "p <<\"EOS\"  #=> \"var\\n\"\n",
    "#{a}\n",
    "EOS\n",
    "puts\n",
    "\n",
    "puts \"変数展開されない\"\n",
    "p <<'EOS'  #=> \"#{a}\\n\"\n",
    "#{a}\n",
    "EOS\n",
    "puts\n",
    "\n",
    "puts \"メソッドの引数として渡す\"\n",
    "language = \"Ruby\"\n",
    "puts language.prepend(<<TEXT)\n",
    "JAVA\n",
    "PHP\n",
    "TEXT\n",
    "\n",
    "puts\n",
    "puts \"直接メソッドを呼び出す\"\n",
    "puts <<TEXT.upcase\n",
    "abc\n",
    "TEXT"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## パーセント記法\n",
    "\n",
    "* 文字列を囲む記号をプログラマが指定できる\n",
    "    * 例えば、文字列の中でダブルクオートを使うときにエスケープしなくてよくなる\n",
    "    * カッコを使う場合は終端は対応する閉じカッコを使う"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"He said \\\"Hello\\\"\"\n",
      "\"He said \\\"Hello\\\"\"\n",
      "\"He said \\\"Hello\\\"\"\n",
      "\"He said \\\"Hello\\\"\"\n",
      "\"He said \\\"Hello\\\"\"\n",
      "\"He said \\\"Hello\\\"\"\n",
      "\"He said \\\"Hello\\\"\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"He said \\\"Hello\\\"\""
      ]
     },
     "execution_count": 130,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### 文字列を囲む記号の例\n",
    "p %&He said \"Hello\"&   #=> \"He said \\\"Hello\\\"\"\n",
    "p %@He said \"Hello\"@   #=> \"He said \\\"Hello\\\"\"\n",
    "p %+He said \"Hello\"+   #=> \"He said \\\"Hello\\\"\"\n",
    "\n",
    "### カッコを使う場合は終端は対応する閉じカッコを使う\n",
    "# p %{He said \"Hello\"{   #=> SyntacError\n",
    "p %{He said \"Hello\"}   #=> \"He said \\\"Hello\\\"\"\n",
    "p %(He said \"Hello\")   #=> \"He said \\\"Hello\\\"\"\n",
    "p %[He said \"Hello\"]   #=> \"He said \\\"Hello\\\"\"\n",
    "p %<He said \"Hello\">   #=> \"He said \\\"Hello\\\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "|記法|生成される文字列|\n",
    "|---|---|\n",
    "|%|ダブルクオート文字列|\n",
    "|%Q|ダブルクオート文字列 (%だけと同じ)|\n",
    "|%q|シングルクオート文字列|\n",
    "|%s|シンボル。式展開無し|\n",
    "|%W|要素がダブルクオート文字列となる配列。要素の区切りは空白文字列|\n",
    "|%w|要素がシングルクオート文字列となる配列。要素の区切りは空白文字列|\n",
    "|%l(大文字アイ)|要素がシンボルの配列。式展開する|\n",
    "|%i |要素がシンボルの配列。式展開しない|\n",
    "|%x|コマンド出力。バッククオートと同じ|\n",
    "|%r|正規表現|\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"He said \\\"Hello\\\"\"\n",
      "\"He said \\\"Hello\\\"\"\n",
      "\"He said \\\"\\#{a}\\\"\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"He said \\\"\\#{a}\\\"\""
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = \"Hello\"\n",
    "p  %{He said \"#{a}\"}   #=> \"He said \\\"Hello\\\"\"\n",
    "p %Q{He said \"#{a}\"}   #=> \"He said \\\"Hello\\\"\"\n",
    "p %q{He said \"#{a}\"}   #=> \"He said \\\"\\#{a}\\\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      ":foo\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       ":foo"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c = \"hoge\"\n",
    "p %s{foo}              #=> :foo\n",
    "#p %s{#{c}}              #=> Error\n",
    "#p %S{c}              #=> Error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\"I\", \"have\", \"a\", \"pen\", \".\"]\n",
      "[\"I\", \"have\", \"a\", \"\\#{b}\", \".\"]\n",
      "[:I, :have, :a, :pen, :\".\"]\n",
      "[:I, :have, :a, :\"\\#{b}\", :\".\"]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[:I, :have, :a, :\"\\#{b}\", :\".\"]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = \"pen\"\n",
    "p %W{I have a #{b} .}   #=> [\"I\", \"have\", \"a\", \"pen\", \".\"]\n",
    "p %w{I have a #{b} .}   #=> [\"I\", \"have\", \"a\", \"\\#{b}\", \".\"]\n",
    "p %I{I have a #{b} .}   #=> [:I, :have, :a, :pen, :\".\"]\n",
    "p %i{I have a #{b} .}   #=> [:I, :have, :a, :\"\\#{b}\", :\".\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"Thu Jun  8 01:34:05 UTC 2017\\n\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"Thu Jun  8 01:34:05 UTC 2017\\n\""
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p %x{date}              #=> \"2017年  1月 13日 金曜日 09:33:09 JST\\n\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/^http:\\/\\//\n",
      "\"^http://\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"^http://\""
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p %r(^http://)          #=> /^http:\\/\\//\n",
    "p %q(^http://)          #=> \"^http://\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 文字列演算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"ab\"\n",
      "\"hogehogehoge\"\n",
      "\"hogefuga\"\n",
      "#<Encoding:UTF-8>\n",
      "#<Encoding:Windows-31J>\n",
      "\"hogefuga\"\n",
      "true\n",
      "true\n",
      "false\n",
      "true\n",
      "-1\n",
      "0\n",
      "1\n",
      "5\n",
      "5\n",
      "5\n",
      "5\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 134,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### +メソッドで文字連結\n",
    "p \"a\" + \"b\"       #=> \"ab\"\n",
    "\n",
    "### *メソッドで繰り返し出力\n",
    "p \"hoge\" * 3      #=> \"hogehogehoge\"\n",
    "\n",
    "### 左辺に数値を指定するとエラーになる\n",
    "#p 3 * \"hoge\"      #=> TypeError\n",
    "\n",
    "### << メソッドにより末尾に連結\n",
    "p \"hoge\" << \"fuga\"  #=> \"hogefuga\"\n",
    "\n",
    "### 異なるエンコード間で文字列操作を行うと例外が発生する (Ruby2.1まで？Ruby2.3.1はエラーにならない)\n",
    "p \"hoge\".encoding                 #=> #<Encoding:UTF-8>\n",
    "p \"fuga\".encode(\"SJIS\").encoding  #=> #<Encoding:Windows-31J>\n",
    "p \"hoge\" + \"fuga\".encode(\"SJIS\")  #=> \"hogefuga\"  参考書的にはエラーになる\n",
    "\n",
    "### 文字列は文字コードで大小を比較する\n",
    "p \"a\" < \"b\"       #=> true\n",
    "p \"ab\" < \"ac\"     #=> true\n",
    "p \"Ab\" < \"Ab\"     #=> false\n",
    "p \"Ab\" == \"Ab\"    #=> true\n",
    "p \"Aa\" <=> \"Ab\"   #=> -1\n",
    "p \"Ab\" <=> \"Ab\"   #=> 0\n",
    "p \"Ac\" <=> \"Ab\"   #=> 1\n",
    "\n",
    "### 文字数の確認\n",
    "p \"abcde\".length      #=> 5\n",
    "p \"abcde\".size        #=> 5\n",
    "p \"あいうえお\".length  #=> 5\n",
    "p \"あいうえお\".size    #=> 5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## sprintfによる整形\n",
    "\n",
    "* 帳票などで行数をそろえるときなどに利用\n",
    "    * 第一引数 : フォーマット, 第二引数以降 : フォーマットしたい値"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "進数の指定\n",
      "\"0b11\"\n",
      "\"010\"\n",
      "\"0xa\"\n",
      "\"0XA\"\n",
      "\n",
      "桁数の指定\n",
      "\" 1\"\n",
      "\"01\"\n",
      "\"  1\"\n",
      "\"001\"\n",
      "\"123.46\"\n",
      "\"123.457\"\n",
      "\"123.4567\"\n",
      "\n",
      "sprintf関数はStringクラスの%演算と同じ結果を得られる\n",
      "\"01\"\n",
      "\"001\"\n",
      "\"1.200 1.80000\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"1.200 1.80000\""
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "puts \"進数の指定\"\n",
    "p sprintf(\"\\%#b\", 3)    #=> \"0b11\"  2進数\n",
    "p sprintf(\"\\%#o\", 8)    #=> \"010\"   8進数\n",
    "p sprintf(\"\\%#x\", 10)   #=> \"0xa\"  16進数\n",
    "p sprintf(\"\\%#X\", 10)   #=> \"0XA\"  16進数 (大文字)\n",
    "puts\n",
    "\n",
    "puts \"桁数の指定\"\n",
    "p sprintf(\"%2d\", 1)          #=> \" 1\"\n",
    "p sprintf(\"%02d\",1)          #=> \"01\"\n",
    "p sprintf(\"%3d\", 1)          #=> \"  1\"\n",
    "p sprintf(\"%03d\",1)          #=> \"001\"\n",
    "p sprintf(\"%05.2f\",123.4567) #=> \"123.46\"\n",
    "p sprintf(\"%05.3f\",123.4567) #=> \"123.457\"\n",
    "p sprintf(\"%05.4f\",123.4567) #=> \"123.4567\"\n",
    "puts\n",
    "\n",
    "puts \"sprintf関数はStringクラスの%演算と同じ結果を得られる\"\n",
    "p \"%02d\" % 1  #=> \"01\"\n",
    "p \"%03d\" % 1  #=> \"001\"\n",
    "p \"%0.3f %0.5f\" % [1.2, 1.8]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# シンボル\n",
    "\n",
    "* 多くのRuby処理系ではシンボルは内部では整数として扱われる\n",
    "    * 文字列と比較して処理が速くなる\n",
    "        * 単にラベルとして文字列を使う場合はシンボルの方が効率が良い\n",
    "            * ハッシュのキーなどによく利用される\n",
    "* (Ruby2.1以前)ガベージコレクションの対象外\n",
    "    * キーの数が限られたケース以外では文字列を使う方が適切(Ruby2.1以前)\n",
    "* 生成された値はSymbolクラスのインスタンスとなる\n",
    "    * <font color=\"red\">「+」といった文字の並びを操作するメソッドが定義されていない</font>\n",
    "        * 動的にシンボルを生成する場合は文字列に変換してからシンボルに変換するという事が良く行われる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      ":foo\n",
      ":foo\n",
      ":foo\n",
      ":foofoobar\n",
      ":foofoobar\n",
      "\"foofoobar\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"foofoobar\""
      ]
     },
     "execution_count": 137,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### シンボルは文字列の先頭にコロンをつける\n",
    "p :\"foo\"       #=> :foo\n",
    "\n",
    "### 文字列の囲み(ダブルクオート)は省略できる。省略するのが一般的\n",
    "p :foo         #=> :foo\n",
    "\n",
    "### パーセント記法でシンボルを生成\n",
    "p %s(foo)      #=> :foo\n",
    "\n",
    "### 動的にシンボルを生成する場合は文字列に変換してからシンボルに変換するという事が良く行われる\n",
    "a = \"foo\"\n",
    "p :\"#{a*2}bar\"             #=> :foofoobar\n",
    "p \"#{a*2}bar\".to_sym       #=> :foofoobar\n",
    "p \"#{a*2}bar\".to_sym.to_s  #=> \"foofoobar\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## オブジェクトの同値性と同一性\n",
    "\n",
    "* 同値性\n",
    "    * 同じ値である。オブジェクトは異なる可能性がある\n",
    "* 同一性\n",
    "    * 同じオブジェクトである。(値が同じである必要は無いが、必然的に値は同じになるはず。。)\n",
    "* シンボルについて\n",
    "    * 文字の並びが同じであれば同一のオブジェクトを参照する\n",
    "* 文字列について\n",
    "    * 文字の並びが同じでも、指定するごとにあらたなStringオブジェクトが生成される\n",
    "* オブジェクトID\n",
    "    * リテラル(数値や文字列など)を指定\n",
    "        * Rubyインタプリタがそのリテラル型に対応するクラスのインスタンスを生成\n",
    "        * 生成されたインスタンスはすべてオブジェクトであり、一意のオブジェクトIDを持つ"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "70290765917780\n",
      "70290765895220\n",
      "2905948\n",
      "2905948\n",
      "8\n",
      "8\n",
      "20\n",
      "20\n",
      "0\n",
      "0\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### 文字列は別オブジェクトID、シンボルは同じオブジェクトID\n",
    "p \"foo\".object_id     #=> (70353350030900などオブジェクトIDが表示される)\n",
    "p \"foo\".object_id     #=> (70353350030760など上と違う値)\n",
    "p :foo.object_id    #=> (2465848などオブジェクトIDが表示される)\n",
    "p :foo.object_id    #=> (2465848など上と同じ値)\n",
    "\n",
    "### nilやtrue、falseなども一つのオブジェクトを参照するためobject_idは変わらない\n",
    "p nil.object_id       #=> 8\n",
    "p nil.object_id       #=> 8\n",
    "p true.object_id      #=> 20\n",
    "p true.object_id      #=> 20\n",
    "p false.object_id     #=> 0\n",
    "p false.object_id     #=> 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "* [Rubyの == と equal? と === と eql? のまとめ](http://d.hatena.ne.jp/k-sato_at_oiax/20100614/1276519946)\n",
    "    * equal?は常にオブジェクトが同じかどうか比較する\n",
    "    * ==, eql?,===はクラスによって意味がかわる\n",
    "        * ===\n",
    "            * case式で値をテストするのに使われる\n",
    "            * 通常は==と同じ\n",
    "                * Module、Range、Regexpでは別の意味になる\n",
    "                * 「パターンマッチ」、「そのクラスに属するかどうか」、「範囲に含まれるかどうか」など\n",
    "        * eql?\n",
    "            * ハッシュの中で「ハッシュのキーとして同じかどうか」を調べるのに使われる。直接はあまり使われない\n",
    "            * ==の比較より硬いイメージ\n",
    "            * 値が同じでも型が違っていればfalse\n",
    "        * ==\n",
    "            * 値の比較に使われる\n",
    "            * 浮動小数点と整数など、型が違っていても値が同じであればtrue\n",
    "            * 数値と文字列は同じものでもfalse\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "false\n",
      "true\n",
      "true\n",
      "true\n",
      "false\n",
      "true\n",
      "false\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### オブジェクトの比較\n",
    "p \"foo\".equal? \"foo\"  #=> false ### オブジェクトが同一かどうかを判定。同一でないのでfalse\n",
    "p \"foo\" === \"foo\"     #=> false ### equal?と同じ。case式でよく使われる\n",
    "p \"foo\".eql? \"foo\"    #=> true  ### 等価演算子で二つのオブジェクトが等しいかどうかを判定。等しいのでtrue\n",
    "p \"foo\" == \"foo\"      #=> true  ### 基本的にeql?と同様だが、型の比較は行わない\n",
    "p 1.to_f.eql? 1       #=> false ### 値は同じでも型が違うのでfalse\n",
    "p 1.to_f == 1         #=> true  ### 型は違うが値が同じなのでtrue\n",
    "p 1 == \"1\"            #=> false ### 整数と文字列はfalse"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 変数代入の挙動の詳細\n",
    "\n",
    "* 1 リテラルを指定すると対応するオブジェクトがメモリ上に生成される\n",
    "* 2 変数を宣言すると変数にオブジェクトへの参照が与えられる\n",
    "    * 変数を他の変数に代入すると両者は同じオブジェクトを指す\n",
    "* 3 変数を参照すると参照先のオブジェクトが返される\n",
    "* 4 変数に代入すると大部分は再代入になる\n",
    "    * 片方の変数に代入しても、もう片方の変数に影響しない\n",
    "        * 代入した方の変数には新たなオブジェクトへの参照が与えられる\n",
    "        * 代入してない方の変数のオブジェクトへの参照はそのまま"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "70099483621100\n",
      "70099483621100\n",
      "\"fuga\"\n",
      "\"hoge\"\n",
      "70099483599120\n",
      "70099483621100\n",
      "\"メソッドの引数\"\n",
      "70099478495120\n",
      "70099478495120\n",
      "70099478458140\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "70099478458140"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = \"hoge\"\n",
    "b = a\n",
    "p a.object_id  #=> (70169318563740など)\n",
    "p b.object_id  #-> (70169318563740などaと同じ)\n",
    "a = \"fuga\"     ### (aに別の値を代入)\n",
    "p a            #=> \"fuga\"\n",
    "p b            #=> \"hoge\"\n",
    "p a.object_id  #=> (70353658141280など先ほどと違う)\n",
    "p b.object_id  #=> (70169318563740など先ほどと同じまま)\n",
    "\n",
    "### メソッドの引数も同様\n",
    "### -> 実引数に指定された変数の参照が仮引数にコピーされる\n",
    "p \"メソッドの引数\"\n",
    "def func(y)       ### メソッドfuncを定義。yを仮引数と呼ぶ。\n",
    "  p y.object_id   ### 1.仮引数yのオブジェクトIDを表示する\n",
    "  y = \"var\"\n",
    "  p y.object_id   ### 2.代入後のオブジェクトIDを表示\n",
    "end\n",
    "x = \"foo\"       ### 変数を宣言\n",
    "p x.object_id   ### 変数xのオブジェクトIDを表示                            (70151085970820など)\n",
    "func(x)         ### 1.仮引数yのオブジェクトIDを表示                        (70151085970820など上と同じ)\n",
    "#                 ### -> 変数xのオブジェクトの参照が、仮引数yにコピーされている\n",
    "#                 ### -> funcのスコープ内からスコープ外のメモリ領域を参照できている\n",
    "#                 ### 2.続けてy = \"var\"が代入された後のyのオブジェクトIDを表示 (70181934504580など上と異なる)\n",
    "#                 ### func(x)としたとき、変数xをメソッドfuncの「実引数」と呼ぶ。\n",
    "#                 ### -> 二つ目のyのオブジェクトIDは再代入が行われているので値が異なる\n",
    "#                 ### -> funcのスコープ内のメモリ領域に別のオブジェクトが生成され、そのオブジェクトへの参照が与えられる"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 破壊的メソッド\n",
    "\n",
    "* 自分自身の内容を変更するメソッド\n",
    "    * 他の変数の参照先にも影響する\n",
    "        * メソッド名に「!」をつけるのが慣習(例外もある)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"foo1\"\n",
      "\"foo1\"\n",
      "\"foo\"\n",
      "\"foo1\"\n",
      "\"foo1\"\n",
      "\"foo\"\n",
      "\"foo\"\n",
      "\"foo\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"foo\""
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v1 = \"foo1\"\n",
    "v2 = v1     ### v2はv1と同じ文字列を参照する\n",
    "p v1        #=> \"foo1\"\n",
    "p v2        #=> \"foo1\" v2はv1と同じ文字列を参照\n",
    "p v1.chop   #=> \"foo\"\n",
    "p v1        #=> \"foo1\" chopの後でも参照先は変更されない\n",
    "p v2        #=> \"foo1\"\n",
    "p v1.chop!  #=> \"foo\"\n",
    "p v1        #=> \"foo\"  chop!の後はv1の参照先が変更されている\n",
    "p v2        #=> \"foo\"  chop!の後はv2の参照先まで変更されている！！"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 文字列とシンボルの違い\n",
    "\n",
    "* 文字列\n",
    "    * 変数に代入すると、たとえ同じ値であってもそれぞれ異なるオブジェクトを指す\n",
    "* シンボル\n",
    "    * 変数が同じオブジェクトを指す"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "70290766755400\n",
      "70290766755380\n",
      "70290766755360\n",
      "2905948\n",
      "2905948\n",
      "2905948\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "2905948"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v1=\"foo\"\n",
    "v2=\"foo\"\n",
    "v3=\"foo\"\n",
    "p v1.object_id   #=> (69836757139180など)  ※ すべて異なるオブジェクトID\n",
    "p v2.object_id   #=> (69836757139160など)\n",
    "p v3.object_id   #=> (69836757139140など)\n",
    "v1=:foo\n",
    "v2=:foo\n",
    "v3=:foo\n",
    "p v1.object_id   #=> (2466908など)  ※ すべて同じオブジェクトID\n",
    "p v2.object_id   #=> (2466908など)\n",
    "p v3.object_id   #=> (2466908など)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# メソッド(関数)\n",
    "\n",
    "* オブジェクトに何らかの処理を行わせる場合はメソッドとして定義しておく\n",
    "    * クラスの中で定義する\n",
    "* メソッドの定義\n",
    "* メソッドの実行\n",
    "* 引数はデフォルト値を設定できる\n",
    "* キーワード引数 (Ruby2.0以降)\n",
    "    * 仮引数名とデフォルト値をコロンで結びつけて定義できる\n",
    "        * 呼び出しにハッシュオブジェクトを渡すことで呼び出し側でどの引数にどのような値を渡したかを明示できる\n",
    "* キーワード引数に任意の引数を使う\n",
    "* 一番最後に評価した値が返る\n",
    "* returnで明示的に返り値を指定できる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "メソッドの実行\n",
      "3\n",
      "7\n",
      "仮引数はデフォルト値を設定できる\n",
      "3\n",
      "101\n",
      "\"\\u30AD\\u30FC\\u30EF\\u30FC\\u30C9\\u5F15\\u6570 (Ruby2.0\\u4EE5\\u964D)\"\n",
      "3\n",
      "101\n",
      "キーワード引数に任意の引数を使う\n",
      "{:c=>3, :d=>4}\n",
      "3\n",
      "一番最後に評価した値が返る\n",
      "11\n",
      "returnで明示的に返り値を指定できる\n",
      "7\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### メソッドaddの定義\n",
    "def add(a,b)  # def式で指定する引数(ここでは a, b) は仮引数と呼ぶ\n",
    "  a + b\n",
    "end\n",
    "\n",
    "#セミコロンを使うと1行で書ける\n",
    "def add2(a,b); a + b; end\n",
    "\n",
    "puts \"メソッドの実行\"\n",
    "p add(1,2)   # メソッドを実行する際に記述する引数(ここでは1, 2)を実引数と呼ぶ\n",
    "p add2(3,4)\n",
    "\n",
    "puts \"仮引数はデフォルト値を設定できる\"\n",
    "def add3(a, b=100)\n",
    "  a + b\n",
    "end\n",
    "\n",
    "p add3(1,2)   # 3\n",
    "p add3(1)     # 101\n",
    "\n",
    "p \"キーワード引数 (Ruby2.0以降)\"\n",
    "def add4(a:, b: 100)\n",
    "  a + b\n",
    "end\n",
    "\n",
    "p add4(a: 1, b: 2)  # 3\n",
    "p add4(a: 1)        # 101\n",
    "#p add4(b: 1)        # ArgumentError\n",
    "\n",
    "puts \"キーワード引数に任意の引数を使う\"\n",
    "def add5(a:, b: 100, **z)\n",
    "  p z    # コンソール上には {:c=>3, :d=>4} が表示される\n",
    "  a + b\n",
    "end\n",
    "\n",
    "p add5(a: 1, b: 2, c: 3, d: 4)   # 3, コンソール上には {:c=>3, :d=>4} が表示される\n",
    "\n",
    "puts \"一番最後に評価した値が返る\"\n",
    "def add6(a, b)\n",
    "  a + b\n",
    "  a + b + b\n",
    "end\n",
    "\n",
    "p add6(3,4)   # 11\n",
    "\n",
    "puts \"returnで明示的に返り値を指定できる\"\n",
    "def add7(a, b)\n",
    "  return a + b\n",
    "  a + b + b\n",
    "end\n",
    "\n",
    "p add7(3,4)   # 7"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# クラス\n",
    "\n",
    "* トップレベル\n",
    "    * クラスの定義式やモジュールの定義式など、定義式の外は「トップレベル」と呼ばれる\n",
    "    * トップレベルで定義されたメソッドはグローバルなサブルーチンのように使用できる\n",
    "        * メソッド呼び出しの際レシーバを記述しない\n",
    "        * いわゆる関数のように、どこからでもグローバルに呼び出す事ができる(一部の例外を除く)\n",
    "* クラスの定義\n",
    "    * メソッドの定義\n",
    "* クラスのインスタンスの生成\n",
    "* クラスのメソッドを実行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 168,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 168,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### BasicFooクラスの定義\n",
    "class BasicFoo\n",
    "  ### testメソッドの定義\n",
    "  def test\n",
    "    1\n",
    "  end\n",
    "end\n",
    "\n",
    "### BasicFooクラスのインスタンスの生成\n",
    "foo = BasicFoo.new\n",
    "\n",
    "### BasicFooクラスのtestメソッドを実行\n",
    "p foo.test"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## attr_* について\n",
    "\n",
    "例を追って說明。\n",
    "\n",
    "* https://www.xmisao.com/2014/02/10/ruby-attr-accessor-attr-reader-attr-writer.html\n",
    "* http://bryankawa.hatenablog.com/entry/2017/01/28/150537\n",
    "\n",
    "* 以下Personクラスがあったとする\n",
    "    * nameメソッドが定義されてないのでエラーになる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "undefined method `name' for #<Person:0x007fa05e41a388>\n"
     ]
    }
   ],
   "source": [
    "class Person\n",
    "end\n",
    "\n",
    "person = Person.new\n",
    "begin\n",
    "  puts person.name\n",
    "rescue NoMethodError => ex\n",
    "  puts ex\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "* nameのreaderメソッドを定義する\n",
    "    * nameメソッドを読み込めた\n",
    "    * ただ、名前が割り当てられた訳ではない"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "nil\n",
      "undefined method `name=' for #<Person:0x007fa05e0e9678>\n"
     ]
    }
   ],
   "source": [
    "class Person\n",
    "  def name ### readerメソッド\n",
    "    @name  ### 単純にインスタンス変数を返す\n",
    "  end  \n",
    "end\n",
    "\n",
    "person = Person.new\n",
    "p person.name\n",
    "begin\n",
    "  person.name = \"Jim\"\n",
    "rescue NoMethodError => ex\n",
    "  puts ex\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "* nameのwriterメソッドを定義する \n",
    "    * reader, writerメソッドを使う事でインスタンス変数@nameを定義して呼び出すことができるようになった"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "nil\n",
      "Jim\n"
     ]
    }
   ],
   "source": [
    "class Person\n",
    "  def name=(str)  ### writerメソッド\n",
    "    @name = str   ### インスタンス変数に値を設定 \n",
    "  end\n",
    "  \n",
    "  def name\n",
    "    @name\n",
    "  end  \n",
    "end\n",
    "\n",
    "person = Person.new\n",
    "p person.name\n",
    "person.name = \"Jim\"\n",
    "puts person.name"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "* 毎回reader,writerメソッドを書くのが面倒\n",
    "  * attr_reader, attr_writerを使うと簡単に書ける\n",
    "      * attr_reader : ゲッターを定義する\n",
    "      * attr_writer : セッターを定義する"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "nil\n",
      "Jim\n"
     ]
    }
   ],
   "source": [
    "class Person2\n",
    "  attr_reader :name\n",
    "  attr_writer :name\n",
    "end\n",
    "\n",
    "person = Person2.new\n",
    "p person.name\n",
    "person.name = \"Jim\"\n",
    "puts person.name"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "* attr_accessorを使うともっと簡単に書ける\n",
    "    * セッターとゲッターを共に定義する\n",
    "* `attr_accessor :name` について\n",
    "    * 「`:name`」はインスタンス変数「`@name`」のこと<font color=\"red\">ではない</font>\n",
    "    * セッター、ゲッターの<font color=\"red\">メソッドの名前</font>が「name=, name」になるということを表している"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "nil\n",
      "Jim\n"
     ]
    }
   ],
   "source": [
    "class Person3\n",
    "  attr_accessor :name\n",
    "end\n",
    "\n",
    "person = Person3.new\n",
    "p person.name\n",
    "person.name = \"Jim\"\n",
    "puts person.name"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "* インスタンス変数 `@name` はpersonオブジェクトに設定することができる\n",
    "  * 他のメソッドからも呼び出せる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello Jim\n",
      "Jim fuga\n"
     ]
    }
   ],
   "source": [
    "class Person\n",
    "  attr_accessor :name\n",
    "  \n",
    "  def greeting\n",
    "    \"Hello #{@name}\"\n",
    "  end\n",
    "  \n",
    "  def hoge\n",
    "    \"#{name} fuga\"\n",
    "  end\n",
    "end\n",
    "\n",
    "person = Person.new\n",
    "person.name = \"Jim\"\n",
    "puts person.greeting\n",
    "puts person.hoge"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### attr_accessorの挙動について\n",
    "\n",
    "* http://qiita.com/jordi/items/7baeb83788c7a8f2070d\n",
    "* attr_accessor\n",
    "    * 引数はシンボルで指定\n",
    "    * シンボルで指定された名前の2つのメソッドを定義する\n",
    "        * メソッド1\n",
    "            * シンボルで指定された名前のメソッドを定義する\n",
    "            * そのメソッドはシンボルの名前の先頭に 「`@`」 を付加したインスタンス変数の値を取り出す\n",
    "            * attr_readerのこと\n",
    "        * メソッド2\n",
    "            * シンボルで指定されたメソッド名の後ろに 「=」 を付加した名前のメソッドを定義する\n",
    "            * そのメソッドは、引数を一つ取り、シンボルの名前の先頭に 「`@`」 を付加したインスタンス変数に設定する\n",
    "            * attr_writerのこと"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## ゲッター、セッターを設定せずにインスタンス変数を取り出す\n",
    "\n",
    "* ゲッターが設定されていないとインスタンス変数にアクセスできない"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "undefined method `message' for #<Fuga:0x007fa05e577d48 @message=\"Hello\">\n"
     ]
    }
   ],
   "source": [
    "class Fuga\n",
    "  # attr_reader :messages    ### ここがコメントアウトされてなければエラーにならない\n",
    "  def initialize\n",
    "    @message = \"Hello\"\n",
    "  end\n",
    "end\n",
    "\n",
    "begin\n",
    "  puts Fuga.new.message  ### attr_readerにて設定されているべきmessageというメソッドが無いのでエラーになる\n",
    "rescue NoMethodError => ex\n",
    "  puts ex\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "* `instance_variables` でインスタンス変数を取得できる\n",
    "* `instance_variable_get` でインスタンス変数の中身を取得できる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[:@message]\n",
      "Hello\n"
     ]
    }
   ],
   "source": [
    "class Fuga\n",
    "  def initialize\n",
    "    @message = \"Hello\"\n",
    "  end\n",
    "end\n",
    "\n",
    "puts Fuga.new.instance_variables\n",
    "puts Fuga.new.instance_variable_get(:@message)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## コメント\n",
    "\n",
    "* 頭にシャープをつける\n",
    "* =begin =endで囲む"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "4\n",
      "5\n",
      "10\n"
     ]
    }
   ],
   "source": [
    "puts 1\n",
    "# puts 2\n",
    "# puts 3\n",
    "puts 4\n",
    "puts 5\n",
    "=begin\n",
    "puts 6\n",
    "puts 7\n",
    "puts 8\n",
    "puts 9\n",
    "=end\n",
    "puts 10"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.3.1",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
